do
    local qca_debug_log_ids = {
        [0x0216] = "LOG_ID_LLM_AFH_RSSIDATA",
        [0x0450] = "LOG_ID_CXM_MWS_TX",
        [0x0460] = "LOG_ID_CXM_MCI_STATS",
    }

    local qca_debug_log_formats = {
        [0x0] = "FMT_PACKET",
    }

    local qca_debug_log_levels = {
        [0x0] = "LOG_LOW",
        [0x1] = "LOG_HIGH",
    }

    local p_qca_debug = Proto("qca_debug", "QCA Debug")
    local f_handle = ProtoField.uint16("qca_debug.log_handle", "Log Handle", base.HEX)
    local f_len = ProtoField.uint16("qca_debug.log_len", "Log Length", base.DEC)
    local f_l2cap_len = ProtoField.uint16("qca_debug.l2cap_len", "L2cap Length", base.DEC)
    local f_cid = ProtoField.uint8("qca_debug.cid", "CID", base.HEX)
    local f_seq = ProtoField.uint8("qca_debug.seq", "Seq Num", base.DEC)
    local f_lost = ProtoField.uint8("qca_debug.log_lost", "Logs Lost/Drop", base.DEC)
    local f_prod_id = ProtoField.uint8("qca_debug.prod_id", "Prod ID", base.HEX)

    local p_qca_debug_log = Proto("qca_debug.log","QCA Debug Log")
    local f_log_id = ProtoField.uint16("qca_debug.log.id", "Log ID", base.HEX, qca_debug_log_ids)
    local f_log_fmt = ProtoField.uint8("qca_debug.log.foramt", "Log Format", base.DEC, qca_debug_log_formats, 0xF0)
    local f_log_level = ProtoField.uint8("qca_debug.log.level", "Log Level", base.DEC, qca_debug_log_levels, 0x03)

    local p_log_timestamp = Proto("qca_debug.log.timestamp", "Timestamp")
    local f_log_timestamp_raw = ProtoField.uint32("qca_debug.log.timestamp.raw", "Raw Timestamp", base.HEX)
    local f_log_timestamp_clkn = ProtoField.uint32("qca_debug.log.timestamp.clkn", "CLKN(312.5usec)", base.HEX, nil, 0x0FFFFFFF)
    local f_log_timestamp_frac = ProtoField.uint32("qca_debug.log.timestamp.frac", "FRAC(32usec)", base.HEX, nil, 0xF0000000)

    local f_log_len = ProtoField.uint16("qca_debug.log.len", "Length", base.DEC)
    local f_log_data = ProtoField.bytes("qca_debug.log.data", "Debug Data", base.NONE)

    local p_afh_rssi = Proto("qca_debug.log.afh", "AFH Rssi Data")
    local p_afh_raw_rssi = Proto("qca_debug.log.afh.raw", "Raw Rssi Data")
    local f_afh_raw_rssi_channel = ProtoField.int8("qca_debug.log.afh.raw.rssi", "Channel")

    local p_afh_band = Proto("qca_debug.log.afh.band", "AFH Interference Band")
    local f_afh_band_bad_chan_cnt = ProtoField.uint8("qca_debug.log.afh.band.bad_chan_cnt", "BadChanCnt")
    local f_afh_band_peak_lo_chan = ProtoField.uint8("qca_debug.log.afh.band.peak_lo_chan", "PeakLoChan")
    local f_afh_band_peak_hi_chan = ProtoField.uint8("qca_debug.log.afh.band.peak_hi_chan", "PeakHiChan")
    local f_afh_band_in_band_avg_rssi = ProtoField.int8("qca_debug.log.afh.band.in_band_avg_rssi", "InBandAvgRssi")


    p_qca_debug.fields = {
        f_handle,
        f_len,
        f_l2cap_len,
        f_cid,
        f_seq,
        f_lost,
        f_prod_id,
    }

    p_qca_debug_log.fields = {
        f_log_id,
        f_log_fmt,
        f_log_level,
        f_log_timestamp,
        f_log_len,
        f_log_data,
    }

    p_log_timestamp.fields = {
        f_log_timestamp_raw,
        f_log_timestamp_clkn,
        f_log_timestamp_frac,
    }

    p_afh_raw_rssi.fields = {
        f_afh_raw_rssi_channel
    }

    p_afh_band.fields = {
        f_afh_band_bad_chan_cnt,
        f_afh_band_peak_lo_chan,
        f_afh_band_peak_hi_chan,
        f_afh_band_in_band_avg_rssi,
    }

    local function afh_rssi_data_decode(buf, pkt, tree)
        local afh_t = tree:add(p_afh_rssi, buf())
        local raw_t = afh_t:add(p_afh_raw_rssi, buf(0, 79))
        for i=0,78,1 do
            local channel = raw_t:add(f_afh_raw_rssi_channel, buf(i, 1), buf(i,1):int(), string.format("Channel %d = %d", i+1, buf(i,1):int()))
        end

        for i=0,2,1 do
            local pos = 79 + i * 4
            local band_t = afh_t:add(p_afh_band, buf(pos, 4), string.format("AFH Interference Band # %d", i+1))
            band_t:add(f_afh_band_bad_chan_cnt, buf(pos, 1))
            band_t:add(f_afh_band_peak_lo_chan, buf(pos+1, 1))
            band_t:add(f_afh_band_peak_hi_chan, buf(pos+2, 1))
            band_t:add(f_afh_band_in_band_avg_rssi, buf(pos+3, 1))
        end
    end

    local function qca_decode(buf, pkt, tree)
        local offset = 0
        local log_handle = buf(offset, 2)
        if log_handle:le_uint() ~= 0x2edc then
            return false
        end

        pkt.cols.protocol:set("QAC Debug")
        local t = tree:add(p_qca_debug, buf(), "QAC Debug")

        t:add_le(f_handle, log_handle)
        offset = offset + 2
        t:add_le(f_len, buf(offset, 2))
        offset = offset + 2
        t:add_le(f_l2cap_len, buf(offset, 2))
        offset = offset + 2
        t:add(f_cid, buf(offset, 1))
        offset = offset + 1
        t:add(f_seq, buf(offset, 1))
        offset = offset + 1
        t:add(f_lost, buf(offset, 1))
        offset = offset + 1
        t:add(f_prod_id, buf(offset, 1))
        offset = offset + 1

        
        while offset < buf:len() do
            local st = t:add(p_qca_debug_log, buf(offset), "QAC Debug Logs")
            local log_id = buf(offset, 2)
            st:add_le(f_log_id, log_id)
            offset = offset + 2
            st:add(f_log_fmt, buf(offset, 1))
            st:add(f_log_level, buf(offset, 1))
            offset = offset + 1
            offset = offset + 1 -- unused data

            local ts = buf(offset, 4)
            local ts_t = st:add_le(p_log_timestamp, ts)
            ts_t:add_le(f_log_timestamp_raw, ts)
            ts_t:add_le(f_log_timestamp_clkn, ts)
            ts_t:add_le(f_log_timestamp_frac, ts)
            offset = offset + 4

            local log_len = buf(offset, 2)
            st:add_le(f_log_len, log_len)
            offset = offset + 2


            local id = log_id:le_uint()
            local data_len = log_len:le_uint()
            if id == 0x0216 then
                afh_rssi_data_decode(buf(offset, data_len):tvb(), pkt, st)
            else
                st:add(f_log_data, buf(offset, data_len))
            end
            offset = offset + data_len
        end

        return true
    end

    local data_dissector = Dissector.get("data")
    function p_qca_debug.dissector(buf, pkt, tree)
        if qca_decode(buf, pkt, tree) then
            -- decode as qca debug
        else
            print("decode as data")
            data_dissector:call(buf, pkt, tree)
        end
    end

    -- local hci_h4 = DissectorTable.get("hci_h4.type")
    -- if (hci_h4 ~= nil) then
    --     hci_h4:add(0x2, p_qca_debug)
    -- end

    local hci_chandle = DissectorTable.get("bthci_acl.chandle")
    if (hci_chandle ~= nil) then
        hci_chandle:add(0xedc, p_qca_debug)
    end
end